//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include "InhibitorsProperty.h"

#include <iostream>
#include <fstream>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <math.h>

#include <zlib.h>
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#define LENGTHLINE  50000
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
InhibitorsProperty::InhibitorsProperty() {

  this->namefileInput  = new String();
  this->namefileResult = new String();
  this->inhibitorsList = new TListE <String> ();
  this->values         = new TListE <double> ();
    
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
InhibitorsProperty::InhibitorsProperty(String* namefileInput, String* namefileResult) {
    
  this->namefileInput  = new String(namefileInput);
  this->namefileResult = new String(namefileResult);
  this->inhibitorsList = new TListE <String> ();
  this->values         = new TListE <double> ();

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
InhibitorsProperty::~InhibitorsProperty() {

  if (this->values)         delete   this->values;
  if (this->inhibitorsList) delete   this->inhibitorsList;
  if (this->namefileInput)  delete   this->namefileInput;
  if (this->namefileResult) delete   this->namefileResult;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void InhibitorsProperty::NamefileInput(String* namefileInput) {
  if (!namefileInput) return;
  *(this->namefileInput) = *namefileInput;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void InhibitorsProperty::NamefileResult(String* namefileResult) {
  if (!namefileResult) return;
  *(this->namefileResult) = *namefileResult;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void InhibitorsProperty::InhibitorsList(TListE <String>* inhibitorsList) {
  *(this->inhibitorsList) = *inhibitorsList;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void InhibitorsProperty::Values(TListE <double>* values) {
  
  if (!values || !values->Length()) return;
  for (int i = 0; i < values->Length(); i++)
    this->values->Add(*(values->Get(i)));

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* InhibitorsProperty::NamefileInput(void) {
  return this->namefileInput;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* InhibitorsProperty::NamefileResult(void) {
  return this->namefileResult;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
TListE <String>* InhibitorsProperty::InhibitorsList(void) {
  return this->inhibitorsList;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
TListE <double>* InhibitorsProperty::Values(void) {
  return this->values;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool InhibitorsProperty::LoadData() {

  if (!this->namefileInput || !this->namefileInput->Length())
    return false;

  this->values->Clear();
  this->inhibitorsList->Clear();

  char              buffer[LENGTHLINE + 1];
  TListE <String>*  column    = new TListE <String> ();

  gzFile fileInput = gzopen(this->namefileInput->Out(), "rb9");
  while (!gzeof(fileInput)) {

    gzgets(fileInput, buffer, LENGTHLINE);
    column->Clear();
    this->SplitColumn(buffer, column, " ");

    if (column->Length() < 3) continue;
    
    this->inhibitorsList->Add(new String(column->Get(1)->Out()));
    this->values->Add(new double(atof(column->Get(2)->Out())));

  }
  gzclose(fileInput);

  if (column) delete column;

  return true;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool InhibitorsProperty::LoadData(String* namefileInput) {
    
  this->NamefileInput(namefileInput);
  
  if (!this->LoadData()) return false;
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool InhibitorsProperty::ComputeEuclidianDistance() {

  if (!this->values->Length() || !this->namefileResult || !this->namefileResult->Length())
    return false;

  double** matrixResult = new double*[this->inhibitorsList->Length()];
  for (int i = 0; i < this->inhibitorsList->Length(); i++) {
    matrixResult[i] = new double[this->inhibitorsList->Length()];
    for (int j = 0; j < this->inhibitorsList->Length(); j++)
      matrixResult[i][j] = 0;
  }

  for (int i = 0; i < this->inhibitorsList->Length(); i++)
    for (int j = i + 1; j < this->inhibitorsList->Length(); j++) 
      matrixResult[i][j] = matrixResult[j][i] = fabs((*(this->values->Get(i))) - (*(this->values->Get(j))));

  fstream fileResult;

  fileResult.open(this->namefileResult->Out(), fstream::out);

  if (fileResult.is_open()) {

    for (int i = 0; i < this->inhibitorsList->Length(); i++) {
      fileResult.width(25);
      fileResult.left;
      fileResult << this->inhibitorsList->Get(i)->Out() << " ";
    }
    fileResult << endl;

    for (int i = 0; i < this->inhibitorsList->Length(); i++) {
      for (int j = 0; j < this->inhibitorsList->Length(); j++) {
        fileResult.width(25);
        fileResult.left;
        fileResult << matrixResult[i][j] << " ";
      }
      fileResult << endl;
    }

    fileResult.close();

  }
  else return false;

  return true;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool InhibitorsProperty::SplitColumn(char* buffer, TListE<String>* columns, const char* characters) {

  if (!buffer || !columns || !characters) return false;

  char *part = strtok(buffer, characters);

  while (part) {
    String* cell = new String(part);
    cell->Trim();
    columns->Add(cell);
    part = strtok(NULL, characters);
  }

  return true;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
